package com.zenithmind.disk.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zenithmind.common.annotation.Log;
import com.zenithmind.common.constant.OperationTypeEnum;
import com.zenithmind.disk.pojo.domain.Files;
import com.zenithmind.disk.pojo.dto.FileDTO;
import com.zenithmind.disk.pojo.query.FileQuery;
import com.zenithmind.disk.pojo.vo.FileVO;
import com.zenithmind.disk.service.FilesService;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@RestController
@RequestMapping("/api/zenithMind/files")
@Tag(name = "存储用户文件信息管理")
public class FilesController {
    @Autowired
    private FilesService filesService;

    @Log(description = "上传文件", operationType = OperationTypeEnum.UPLOAD)
    @Operation(summary = "上传文件-普通用户")
    @PostMapping("/uploadFile")
    public Result<FileVO> uploadFile(MultipartFile file, String userId, String parentId){
        log.info("上传文件：{},{},{}", file,userId,parentId);
        FileVO fileVO = filesService.uploadFile(file, userId, parentId);
        return Result.success(fileVO);
    }

    @Log(description = "创建文件夹", operationType = OperationTypeEnum.ADD)
    @Operation(summary = "创建文件夹-普通用户")
    @PostMapping("/createFolder")
    public Result<FileVO> createFolder(@RequestBody FileDTO fileDTO){
        log.info("创建文件夹：{}", fileDTO);
        FileVO fileVO1 = filesService.createFolder(fileDTO);
        return Result.success(fileVO1);
    }

    @Log(description = "查询文件列表", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "查询文件列表-普通用户")
    @GetMapping("/listFiles")
    public Result<List<FileVO>> listFiles(String userId, String parentId){
        log.info("查询文件列表：{},{}", userId, parentId);
        List<FileVO> fileVO = filesService.listFiles(userId, parentId);
        return Result.success(fileVO);
    }

    @Log(description = "重命名文件", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "重命名文件-普通用户")
    @PutMapping("/renameFile")
    public Result<FileVO> renameFile(@RequestBody FileDTO fileDTO){
        log.info("重命名文件：{}", fileDTO);
        FileVO fileVO = filesService.renameFile(fileDTO);
        return Result.success(fileVO);
    }

    @Log(description = "移动文件", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "移动文件-普通用户")
    @PutMapping("/moveFile")
    public Result<Boolean> moveFile(String fileId, String targetId, String userId){
        log.info("移动文件：{},{},{}", fileId, targetId, userId);
        boolean b = filesService.moveFile(fileId, targetId, userId);
        return Result.success(b);
    }

    @Log(description = "删除文件", operationType = OperationTypeEnum.DELETE)
    @Operation(summary = "删除文件-普通用户")
    @DeleteMapping("/deleteFile")
    public Result<Boolean> deleteFile(String fileId, String userId){
        log.info("删除文件：{},{}", fileId, userId);
        boolean b = filesService.deleteFile(fileId, userId);
        return Result.success(b);
    }

    @Log(description = "获取文件信息", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取文件信息-普通用户")
    @GetMapping("/getFileInfo")
    public Result<FileVO> getFileInfo(String fileId){
        FileVO fileVO = filesService.getFileInfo(fileId);
        return Result.success(fileVO);
    }

    @Log(description = "获取文件路径", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取文件路径-普通用户")
    @GetMapping("/getFilePath")
    public Result<String> getFilePath(String fileId, String userId){
        String filePath = filesService.getFilePath(fileId, userId);
        return Result.success(filePath);
    }

    @Log(description = "下载文件", operationType = OperationTypeEnum.DOWNLOAD)
    @Operation(summary = "下载文件-普通用户")
    @GetMapping("/downloadFile")
    public void downloadFile(String fileId, String userId, HttpServletResponse response) throws IOException {
        // 获取文件路径
        String filePath = filesService.downloadFile(fileId, userId);
        if (filePath == null) {
            throw new RuntimeException("文件不存在或无法下载");
        }
        
        // 获取文件信息
        Files fileInfo = filesService.getById(fileId);
        if (fileInfo == null) {
            throw new RuntimeException("文件不存在");
        }

        // 获取文件
        File downloadFile = new File(filePath);
        if (!downloadFile.exists()) {
            throw new RuntimeException("文件不存在");
        }

        // 设置响应头
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileInfo.getFileName(), "UTF-8"));
        response.setContentLength((int) downloadFile.length());

        // 输出文件流
        try (FileInputStream fis = new FileInputStream(downloadFile);
             OutputStream os = response.getOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            os.flush();
        }
    }

    @Log(description = "下载文件夹", operationType = OperationTypeEnum.DOWNLOAD)
    @Operation(summary = "下载文件夹-普通用户")
    @GetMapping("/downloadFolder")
    public void downloadFolder(String folderId, String userId, HttpServletResponse response) throws IOException {
        // 获取文件夹信息
        Files folderInfo = filesService.getById(folderId);
        if (folderInfo == null || folderInfo.getIsDirectory() != 1) {
            throw new RuntimeException("文件夹不存在");
        }

        // 检查用户权限
        if (!folderInfo.getUserId().equals(userId)) {
            throw new RuntimeException("用户无权限操作");
        }

        // 设置响应头
        String zipFileName = folderInfo.getFileName() + ".zip";
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));

        // 创建ZIP输出流
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
            // 递归添加文件夹内容到ZIP
            addFolderToZip(folderInfo.getId(), folderInfo.getFileName(), userId, zipOut);
        }
    }

    /**
     * 递归添加文件夹内容到ZIP
     */
    private void addFolderToZip(String folderId, String folderPath, String userId, ZipOutputStream zipOut) throws IOException {
        // 获取文件夹下的所有文件和子文件夹
        LambdaQueryWrapper<Files> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Files::getParentId, folderId)
                .eq(Files::getStatus, 1)
                .eq(Files::getUserId, userId);
        List<Files> filesList = filesService.list(queryWrapper);

        for (Files file : filesList) {
            String entryPath = folderPath + "/" + file.getFileName();
            
            if (file.getIsDirectory() == 1) {
                // 如果是文件夹，递归处理
                // 为空文件夹创建条目
                ZipEntry folderEntry = new ZipEntry(entryPath + "/");
                zipOut.putNextEntry(folderEntry);
                zipOut.closeEntry();
                
                // 递归添加子文件夹内容
                addFolderToZip(file.getId(), entryPath, userId, zipOut);
            } else {
                // 如果是文件，直接添加到ZIP
                String filePath = filesService.getFilePath(file.getId(), userId);
                if (filePath != null) {
                    File fileToZip = new File(filePath);
                    if (fileToZip.exists()) {
                        // 添加文件到ZIP
                        ZipEntry zipEntry = new ZipEntry(entryPath);
                        zipOut.putNextEntry(zipEntry);
                        
                        try (FileInputStream fis = new FileInputStream(fileToZip)) {
                            byte[] buffer = new byte[8192];
                            int length;
                            while ((length = fis.read(buffer)) > 0) {
                                zipOut.write(buffer, 0, length);
                            }
                        }
                        zipOut.closeEntry();
                    }
                }
            }
        }
    }

    @Log(description = "分页查询文件列表", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "分页查询文件列表")
    @GetMapping("/filePage")
    public Result<PageResult<FileVO>> filePage(FileQuery fileQuery) {
        log.info("分页查询文件列表：{}", fileQuery);
        PageResult<FileVO> fileVOPageResult = filesService.filePage(fileQuery);
        return Result.success(fileVOPageResult);
    }

    @Log(description = "批量删除文件", operationType = OperationTypeEnum.DELETE)
    @Operation(summary = "批量删除文件-管理员")
    @DeleteMapping("/deleteBatchFiles")
    public Result<Boolean> deleteBatchFiles(@RequestBody List<String> ids) {
        log.info("批量删除文件：{}", ids);
        boolean result = filesService.deleteBatchFiles(ids);
        return Result.success(result);
    }

    @Log(description = "添加或修改文件", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "添加或修改文件-管理员")
    @PostMapping("/addOrUpdateFile")
    public Result<FileVO> addOrUpdateFile(@RequestBody Files file) {
        log.info("添加或修改文件：{}", file);
        FileVO fileVO = filesService.addOrUpdateFileByAdmin(file);
        return Result.success(fileVO);
    }
}
